// 
//  StringEncryptionHelper.cs
//  
//  Author:
//       Ray Shaw <demogodyou@gmail.com>
// 
//  Copyright (c) 2009 Ray Shaw(xiaolei)
// 
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
// 
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU General Public License for more details.
//  
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 
//------------------------------------------------------------------------------
// <auto-generated>
//     此代码由工具生成。
//     运行时版本:2.0.50727.3053
//
//     对此文件的更改可能会导致不正确的行为，并且如果
//     重新生成代码，这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.Security.Cryptography;


namespace SharpNote.Core.Security
{
	/// <summary>
	/// String data encryption and decryption helper.
	/// </summary>
	public class StringEncryptionHelper
	{
		public StringEncryptionHelper ()
		{
		}
		
		/// <summary>
		/// Compute hash byte array use HMACMD5.
		/// </summary>
		/// <param name="plaintext">plain text.
		/// A <see cref="System.String"/>
		/// </param>
		/// <param name="privateKey">private key.
		/// A <see cref="System.Byte[]"/>
		/// </param>
		/// <returns>byte array.
		/// A <see cref="System.Byte[]"/>
		/// </returns>
		public static byte[] GetMD5HashBytes(string plaintext, byte[] privateKey)
		{
			if(plaintext == null || privateKey == null || privateKey.Length == 0){ return new byte[0];}
			
			byte[] result = null;
			HMACMD5 hmacmd5 =new HMACMD5(privateKey);
			
			try
			{
				byte[] plaintextBytes = System.Text.Encoding.UTF8.GetBytes(plaintext);
				result = hmacmd5.ComputeHash(plaintextBytes);
			}finally
			{
				hmacmd5.Clear();
			}
				
			return result;
		}
		
		/// <summary>
		/// Compute hash byte array use HMACMD5.
		/// </summary>
		/// <param name="plaintext">plain text.
		/// A <see cref="System.String"/>
		/// </param>
		/// <param name="privateKey">private key.
		/// A <see cref="System.String"/>
		/// </param>
		/// <returns>byte array.
		/// A <see cref="System.Byte[]"/>
		/// </returns>
		public static byte[] GetMD5HashBytes(string plaintext, string privateKey)
		{
			if(plaintext == null){ return new byte[0];}
			
			byte[] keyBytes = System.Text.Encoding.UTF8.GetBytes(privateKey);
			return GetMD5HashBytes(plaintext, keyBytes);
		}
		
		/// <summary>
		/// Compute hash byte array use MD5.
		/// </summary>
		/// <param name="plaintext">plain text.
		/// A <see cref="System.String"/>
		/// </param>
		/// <param name="privateKey">private key.
		/// A <see cref="System.String"/>
		/// </param>
		/// <returns>byte array.
		/// A <see cref="System.Byte[]"/>
		/// </returns>
		public static byte[] GetMD5HashBytes(string plaintext)
		{
			if(plaintext == null){ return new byte[0];}
			
			byte[] plaintextBytes = System.Text.Encoding.UTF8.GetBytes(plaintext);
			MD5 md5 = MD5.Create();
			try
			{
				return md5.ComputeHash(plaintextBytes);
			}finally
			{
			  md5.Clear();	
			}
		}
		
		/// <summary>
        /// Encrypt plain text.
        /// </summary>
        /// <param name="plainText">plain text</param>
        /// <param name="password">use this as private key to encrypt plain text.</param>
        /// <param name="cipherText">clipher text after encryption.</param>
        /// <returns>if success</returns>
        public static bool EncryptString(string plainText, string password, 
            out string cipherText)
        {
            cipherText = string.Empty;
            if (plainText == null || password == null) { return false; }

            try
            {
                MD5 md5 = MD5.Create();
                byte[] salt = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
                Rfc2898DeriveBytes secretKey = new Rfc2898DeriveBytes(password, salt);

                RijndaelManaged rijndael = new RijndaelManaged();
                try
                {
                    using (ICryptoTransform encryptor = rijndael.CreateEncryptor(secretKey.GetBytes(32),
                        secretKey.GetBytes(16)))
                    {
                        using (System.IO.MemoryStream memory = new System.IO.MemoryStream())
                        {
                            using (CryptoStream cryptoStream = new CryptoStream(memory, encryptor,
                                CryptoStreamMode.Write))
                            {
                                byte[] plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
                                cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
                                cryptoStream.FlushFinalBlock();

                                byte[] result = memory.ToArray();

                                cipherText = Convert.ToBase64String(result);
                                return true;
                            }
                        }
                    }
                }
                finally
                {
                    md5.Clear();
                    rijndael.Clear();
                }
            }
            catch { return false; }
        }

		/// <summary>
		///  Decrypt string with password.
		/// </summary>
		/// <param name="ciphertext">cipher text.
		/// A <see cref="System.String"/>
		/// </param>
		/// <param name="password">password.
		/// A <see cref="System.String"/>
		/// </param>
		/// <param name="plainText">plain text.
		/// A <see cref="System.String"/>
		/// </param>
		/// <returns>if success.
		/// A <see cref="System.Boolean"/>
		/// </returns>
        public static bool DecryptString(string ciphertext, byte[] password,
            out string plainText)
        {
            plainText = string.Empty;
            if (ciphertext == null || password == null || password.Length == 0) { return false; }

            try
            {
                RijndaelManaged rijndael = new RijndaelManaged();
                MD5 md5 = MD5.Create();
                try
                {
                    byte[] salt = md5.ComputeHash(password);
                    Rfc2898DeriveBytes secretKey = new Rfc2898DeriveBytes(System.Text.Encoding.UTF8.GetString(password), salt);
                    using (ICryptoTransform decryptor = rijndael.CreateDecryptor(secretKey.GetBytes(32),
                        secretKey.GetBytes(16)))
                    {
                        byte[] cipherTextBytes = Convert.FromBase64String(ciphertext);
                        using (System.IO.MemoryStream memory = new System.IO.MemoryStream(cipherTextBytes))
                        {
                            using (CryptoStream cryptoStream = new CryptoStream(memory, decryptor, CryptoStreamMode.Read))
                            {
                                byte[] plainTextBytes = new byte[cipherTextBytes.Length];
                                int decryptLength = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);

                                plainText = System.Text.Encoding.UTF8.GetString(plainTextBytes, 0, decryptLength);
                                return true;
                            }
                        }
                    }
                }
                finally
                {
                    rijndael.Clear();
                    md5.Clear();
                }
            }
            catch { return false; }
        }
		
		/// <summary>
        /// Encrypt plain text.
        /// </summary>
        /// <param name="plainText">plain text</param>
        /// <param name="password">use this as private key to encrypt plain text.</param>
        /// <param name="cipherText">clipher text after encryption.</param>
        /// <returns>if success</returns>
        public static bool EncryptString(string plainText, byte[] password, 
            out string cipherText)
        {
            cipherText = string.Empty;
            if (plainText == null || password == null) { return false; }

            try
            {
                MD5 md5 = MD5.Create();
                byte[] salt = md5.ComputeHash(password);
                Rfc2898DeriveBytes secretKey = new Rfc2898DeriveBytes(System.Text.Encoding.UTF8.GetString(password), salt);

                RijndaelManaged rijndael = new RijndaelManaged();
                try
                {
                    using (ICryptoTransform encryptor = rijndael.CreateEncryptor(secretKey.GetBytes(32),
                        secretKey.GetBytes(16)))
                    {
                        using (System.IO.MemoryStream memory = new System.IO.MemoryStream())
                        {
                            using (CryptoStream cryptoStream = new CryptoStream(memory, encryptor,
                                CryptoStreamMode.Write))
                            {
                                byte[] plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
                                cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
                                cryptoStream.FlushFinalBlock();

                                byte[] result = memory.ToArray();

                                cipherText = Convert.ToBase64String(result);
                                return true;
                            }
                        }
                    }
                }
                finally
                {
                    md5.Clear();
                    rijndael.Clear();
                }
            }
            catch { return false; }
        }

		/// <summary>
		///  Decrypt string with password.
		/// </summary>
		/// <param name="ciphertext">cipher text.
		/// A <see cref="System.String"/>
		/// </param>
		/// <param name="password">password.
		/// A <see cref="System.String"/>
		/// </param>
		/// <param name="plainText">plain text.
		/// A <see cref="System.String"/>
		/// </param>
		/// <returns>if success.
		/// A <see cref="System.Boolean"/>
		/// </returns>
        public static bool DecryptString(string ciphertext, string password,
            out string plainText)
        {
            plainText = string.Empty;
            if (ciphertext == null || password == null) { return false; }

            try
            {
                RijndaelManaged rijndael = new RijndaelManaged();
                MD5 md5 = MD5.Create();
                try
                {
                    byte[] salt = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
                    Rfc2898DeriveBytes secretKey = new Rfc2898DeriveBytes(password, salt);
                    using (ICryptoTransform decryptor = rijndael.CreateDecryptor(secretKey.GetBytes(32),
                        secretKey.GetBytes(16)))
                    {
                        byte[] cipherTextBytes = Convert.FromBase64String(ciphertext);
                        using (System.IO.MemoryStream memory = new System.IO.MemoryStream(cipherTextBytes))
                        {
                            using (CryptoStream cryptoStream = new CryptoStream(memory, decryptor, CryptoStreamMode.Read))
                            {
                                byte[] plainTextBytes = new byte[cipherTextBytes.Length];
                                int decryptLength = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);

                                plainText = System.Text.Encoding.UTF8.GetString(plainTextBytes, 0, decryptLength);
                                return true;
                            }
                        }
                    }
                }
                finally
                {
                    rijndael.Clear();
                    md5.Clear();
                }
            }
            catch { return false; }
        }
		
		/// <summary>
        /// Encrypt plain text.
        /// </summary>
        /// <param name="plainText">plain text</param>
        /// <param name="password">use this as private key to encrypt plain text.</param>
        /// <param name="cipherText">clipher text after encryption.</param>
        /// <returns>if success</returns>
        public static bool EncryptString(string plainText, string password, 
            out byte[] cipherTextBytes)
        {
            cipherTextBytes = new byte[0];
            if (plainText == null || password == null) { return false; }

            try
            {
                MD5 md5 = MD5.Create();
                byte[] salt = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
                Rfc2898DeriveBytes secretKey = new Rfc2898DeriveBytes(password, salt);

                RijndaelManaged rijndael = new RijndaelManaged();
                try
                {
                    using (ICryptoTransform encryptor = rijndael.CreateEncryptor(secretKey.GetBytes(32),
                        secretKey.GetBytes(16)))
                    {
                        using (System.IO.MemoryStream memory = new System.IO.MemoryStream())
                        {
                            using (CryptoStream cryptoStream = new CryptoStream(memory, encryptor,
                                CryptoStreamMode.Write))
                            {
                                byte[] plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
                                cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
                                cryptoStream.FlushFinalBlock();

                                cipherTextBytes = memory.ToArray();

                                return true;
                            }
                        }
                    }
                }
                finally
                {
                    md5.Clear();
                    rijndael.Clear();
                }
            }
            catch { return false; }
        }

		/// <summary>
		///  Decrypt string with password.
		/// </summary>
		/// <param name="ciphertext">cipher text.
		/// A <see cref="System.String"/>
		/// </param>
		/// <param name="password">password.
		/// A <see cref="System.String"/>
		/// </param>
		/// <param name="plainText">plain text.
		/// A <see cref="System.String"/>
		/// </param>
		/// <returns>if success.
		/// A <see cref="System.Boolean"/>
		/// </returns>
        public static bool DecryptString(byte[] cipherTextBytes, string password,
            out string plainText)
        {
            plainText = string.Empty;
            if (cipherTextBytes == null || cipherTextBytes.Length == 0 || password == null) { return false; }

            try
            {
                RijndaelManaged rijndael = new RijndaelManaged();
                MD5 md5 = MD5.Create();
                try
                {
                    byte[] salt = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
                    Rfc2898DeriveBytes secretKey = new Rfc2898DeriveBytes(password, salt);
                    using (ICryptoTransform decryptor = rijndael.CreateDecryptor(secretKey.GetBytes(32),
                        secretKey.GetBytes(16)))
                    {
                        using (System.IO.MemoryStream memory = new System.IO.MemoryStream(cipherTextBytes))
                        {
                            using (CryptoStream cryptoStream = new CryptoStream(memory, decryptor, CryptoStreamMode.Read))
                            {
                                byte[] plainTextBytes = new byte[cipherTextBytes.Length];
                                int decryptLength = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);

                                plainText = System.Text.Encoding.UTF8.GetString(plainTextBytes, 0, decryptLength);
                                return true;
                            }
                        }
                    }
                }
                finally
                {
                    rijndael.Clear();
                    md5.Clear();
                }
            }
            catch { return false; }
        }
	}
}
